﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Windows;
using FinosLibrary;
namespace FinosLibrary {
    public class Invoker {
        public MethodInfo mi;
        public object obj;
        public object[] arg;
        private List<Invoker> list;
        public void add(Invoker more) {
            if (list == null) list = new List<Invoker>();
            list.Add(more);
        }
        public void Invoke() {
            try {
                if (list != null) {
                    foreach (Invoker child in list) {
                        child.arg = arg;
                        child.Invoke();
                    }
                }
                mi.Invoke(obj, arg);
            } catch (Exception e) {
                MessageBox.Show(e.InnerException != null ? e.InnerException.Message : e.Message, obj.GetType().Name + "." + mi.Name, MessageBoxButton.OK);
            }
        }
        public void SetArg(Package p) {
            ParameterInfo[] ps = mi.GetParameters();
            arg = new object[ps.Length];
            if (arg.Length > 0) {
                Type pt = ps[0].ParameterType;
                if (pt == typeof(string)) {
                    arg[0] = p.body;
                } else if (pt == typeof(Package)) {
                    arg[0] = p;
                } else {
                    arg[0] = typeof(Package).GetMethod("getBody").MakeGenericMethod(pt).Invoke(p, null);
                }
            }
        }
        public void SetArg(Package p, object client) {
            ParameterInfo[] ps = mi.GetParameters();
            arg = new object[ps.Length];
            if (arg.Length > 0) {
                arg[0] = client;
            }
            if (arg.Length > 1) {
                Type pt = ps[1].ParameterType;
                if (pt == typeof(string)) {
                    arg[1] = p.body;
                } else if (pt == typeof(Package)) {
                    arg[1] = p;
                } else {
                    arg[1] = typeof(Package).GetMethod("getBody").MakeGenericMethod(pt).Invoke(p, null);
                }
            }
        }
    }
    public class LogicParse {
        public static void Parse(object logic, Dictionary<string, Invoker> map) {
            foreach (MethodInfo mi in logic.GetType().GetMethods()) {
                MessageMethodAttribute ma = Attribute.GetCustomAttribute(mi, typeof(MessageMethodAttribute), true) as MessageMethodAttribute;
                if (ma == null) continue;
                if (map.ContainsKey(mi.Name))
                    map[mi.Name].add(new Invoker() { mi = mi, obj = logic });
                else
                    map[mi.Name] = new Invoker() { mi = mi, obj = logic };
            }
            foreach (FieldInfo fi in logic.GetType().GetFields()) {
                AutoWireAttribute autoa = Attribute.GetCustomAttribute(fi, typeof(AutoWireAttribute)) as AutoWireAttribute;
                if (autoa == null) continue;
                Type ft = fi.FieldType;
                if (autoa.singleton) {
                    fi.SetValue(logic, ft.GetInstance(autoa.args));
                } else {
                    fi.SetValue(logic, Activator.CreateInstance(ft, autoa.args));
                }
            }
            foreach (PropertyInfo pi in logic.GetType().GetProperties()) {
                AutoWireAttribute autoa = Attribute.GetCustomAttribute(pi, typeof(AutoWireAttribute)) as AutoWireAttribute;
                if (autoa == null) continue;
                Type ft = pi.PropertyType;
                if (autoa.singleton) {
                    pi.SetValue(logic, ft.GetInstance(autoa.args), null);
                } else {
                    pi.SetValue(logic, Activator.CreateInstance(ft, autoa.args), null);
                }
            }
        }
    }
}
